/**
 * 
 */
package com.designpattern.design.singleton.doublecheck;

/**
 * 单例模式-双重检查实现线程安全
 * 
 * @author zhangyang
 *
 */
public class SingletionDoubleCheckTest {

	public static void main(String[] args) {
		System.out.println(SingletionDoubleCheckDemo.getinstance().hashCode());
		System.out.println(SingletionDoubleCheckDemo.getinstance().hashCode());
	}
}

class SingletionDoubleCheckDemo {
	// 私有化类构造器
	private SingletionDoubleCheckDemo() {

	}

	// 使用volatile关键字定义一个私有的静态变量
	/**
	 * 为什么volatile能实现 
	 * 1.volatile关键字的作用就是不同线程之间内存可见性，也就是说不同线程之间发现instance对象是一个
	 * 2.禁止指令重排序 new关键字底层有4个指令 定义一个变量 生成一个对象 对象初始化 将对象的hashCode赋予变量
	 * 但是这4部不是按照顺序进行的，所以会不安全，加上禁止指令重排序之后这四部顺序进行多线程之间都按照这个顺序执行
	 */
	private static volatile SingletionDoubleCheckDemo instance;

	public static SingletionDoubleCheckDemo getinstance() {
		if (instance == null) {
			/**
			 * synchronized这个SingletionDoubleCheckDemo保证下面进行的时候new语句只能第一个线程
			 * 其他的线程由于volatile关键字在第二个if的时候就不为空，直接退出	
			 */
			synchronized (SingletionDoubleCheckDemo.class) {
				if (instance == null) {
					instance = new SingletionDoubleCheckDemo();
				}
			}
		}
		return instance;
	}

}